package nl.haemers.collections 
{
	import nl.haemers.collections.interfaces.IIterator;
	import nl.haemers.collections.interfaces.ICollection;
	import nl.haemers.collections.interfaces.IIterable;
	import nl.haemers.utils.Logger;
	
	import nl.haemers.collections.errors.UnsupportedOperationException;
	/**
	 * @author Jonathan Haemers
	 */
	public class AbstractCollection implements ICollection
	{
		
		
		public function AbstractCollection() 
		{
			super();
		}
		
		/** Public methods **/
		/*
		public function getCollection() : Vector.<Object>
		{
			return collection;
		}
		*/
		/**
		 * @inheritDoc
		 */
		public function add(e:Object):Boolean
		{
			throw new UnsupportedOperationException();
		}
		
		/**
		 * @inheritDoc
		 */
		public function addAll(collection:ICollection):Boolean
		{
			var result:Boolean = false;
			var it:IIterator = collection.iterator();
			while (it.hasNext()) {
				if (add(it.next())) {
					result = true;
				}
			}
			return result;
		}
		
		/**
		 * @inheritDoc
		 */
		public function clear():void
		{
			var it:IIterator = iterator();
			while (it.hasNext()) 
			{
				it.next();
				it.remove();
			}
		}
		
		/**
		 * @inheritDoc
		 */
		public function contains(e:Object):Boolean
		{
			var it:IIterator = iterator();
			if (e != null) {
				while (it.hasNext()) 
				{
					if (e == it.next()) 
					{
						return true;
					}
				}
			} 
			else 
			{
				while (it.hasNext()) 
				{
					if (!it.next()) {
						return true;
					}
				}
			}
			return false;
		}
		
		/**
		 * @inheritDoc
		 */
		public function containsAll(collection:ICollection):Boolean
		{
			var it:IIterator = collection.iterator();
			while (it.hasNext()) 
			{
				if (!contains(it.next())) 
				{
					return false;
				}
			}
			return true;
		}
		
		/**
		 * @inheritDoc
		 */
		public function isEmpty():Boolean
		{
			return size == 0;
		}
		
		/**
		 * @inheritDoc
		 */
		public function remove(e:Object=null):Boolean
		{
			var it:IIterator = iterator();
			if (e != null) 
			{
				while (it.hasNext()) 
				{
					if (e == it.next()) 
					{
						it.remove();
						return true;
					}
				}
			}
			else 
			{
				while (it.hasNext()) 
				{
					if (!it.next()) 
					{
						it.remove();
						return true;
					}
				}
			}
			
			return false;
		}
		
		/**
		 * @inheritDoc
		 */
		public function removeAll(collection:ICollection):Boolean
		{
			var result:Boolean = false;
			var it:IIterator = iterator();
			
			while (it.hasNext()) 
			{
				if (collection.contains(it.next())) 
				{
					it.remove();
					result = true;
				}
			}
			return result;
		}
		
		/**
		 * @inheritDoc
		 */
		public function retainAll(collection:ICollection):Boolean
		{
			var result:Boolean = false;
			var it:IIterator = iterator();
			while (it.hasNext()) 
			{
				if (!collection.contains(it.next())) 
				{
					it.remove();
					result = true;
				}
			}
			return result;
		}
		
		/**
		 * @inheritDoc
		 */
		public function toArray():Array
		{
			var size:int = size;
			var index:int = 0;
			
			var it:IIterator = iterator();
			var array:Array = [];
			//Build backwards loop for a 10% increment in speed :)
			while(size--)
			{
				// TODO: don't know if this is gonna work need to test the speed...
				array[index++] = it.next();
			}
			/*
			while (index < size) 
			{
				array[index++] = it.next();
			}
			*/
			return array;
		}
		
		/**
		 * @inheritDoc
		 */
		public function toString() : String
		{
			if (isEmpty()) {
				return "[]";
			}

			var buffer:String = "[";
			var it:IIterator = iterator();
			var next:Object;
			
			while (it.hasNext()) 
			{
				next = it.next();
				//Little optimalisation
				buffer += (next != this) ?  next : "(this Collection)";
				buffer += (it.hasNext()) ? ", " : "]";
			}
			
			return buffer;
		}
		
		/** Public abstract methods **/
		/**
		 * @inheritDoc
		 */
		// Java doesn't have an implementation of this method
		public function equals(e:Object):Boolean
		{
			return e;
		}
		
		/**
		 * @inheritDoc
		 */
		// Java doesn't have an implementation of this method
		public function hashCode():int
		{
			return NaN;
		}
		
		/**
		 * @inheritDoc
		 */
		public function iterator():IIterator 
		{
			return null;
		}
		
		/**
		 * @inheritDoc
		 */
		public function get size():int
		{
			return NaN;
		}
		
	}

}